package tjs.study.mini.spingmvcmini.config.servlet;

import lombok.SneakyThrows;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.util.Assert;

import java.lang.reflect.Method;

/**
 * @author nicky
 * @date 2021/9/7 下午4:02
 */
public class HandlerMethod {
    /**
     * 为什么存字符串，因为可能tomact已经开始接受请求了，但是ioc还没加载完
     * 为什么不强制先加载完，因为这样做破坏了bean的生命周期
     * 1. 先存字符串beanName
     * {@link HandlerMethod#HandlerMethod(java.lang.String, org.springframework.beans.factory.BeanFactory, java.lang.reflect.Method)}
     * 2. 请求进来时，再判断是否为字符串，是则beanFactory.getBean获取
     * {@link HandlerMethod#createWithResolvedBean()}
     */
    private Object bean;

    private BeanFactory beanFactory;

    private Method targetMethod;

    public HandlerMethod(Object bean, BeanFactory beanFactory, Method targetMethod) {
        this.bean = bean;
        this.beanFactory = beanFactory;
        this.targetMethod = targetMethod;
    }

    public HandlerMethod createWithResolvedBean() {
        if (this.bean instanceof String) {
            //为什么存字符串，因为可能tomact已经开始接受请求了，但是ioc还没加载完
            Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
            String beanName = (String) this.bean;
            this.bean = this.beanFactory.getBean(beanName);
        }
        return this;
    }

    @SneakyThrows
    public Object doInvoke(Object... providedArgs) {
        return targetMethod.invoke(this.bean, providedArgs);
    }

    public Object getBean() {
        return bean;
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }

    public Method getTargetMethod() {
        return targetMethod;
    }

    public void setTargetMethod(Method targetMethod) {
        this.targetMethod = targetMethod;
    }
}
